package com.demo.wechat.controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@SuppressWarnings("ConstantConditions")
@RestController
@PropertySource("classpath:wechat-web-login.file")
public class AppController implements EnvironmentAware {

    private Environment env;

    @GetMapping("/hello")
    public String testHello() {
        return "hello...";
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.env = environment;
        // 测试获取wechat-web-login.file的wechat.appid属性值
        System.out.println(this.env.getProperty("wechat.appid"));
    }

    /*
        微信网页授权登录 Open in WechatDevTool
        https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx626ad78df43f35e9&redirect_uri=http://127.0.0.1/wechat-login/app/index&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

     */
    @GetMapping("/index")
    public String index(WebRequest request, HttpServletResponse response) throws IOException {
        if (request.getAttribute("user", WebRequest.SCOPE_SESSION) == null) {
            MultiValueMap<String, String> queryMap = new LinkedMultiValueMap<>();
            queryMap.add("appid", env.getProperty("wechat.appid"));
            queryMap.add("redirect_uri", "http://".concat(this.env.getProperty("wechat.redirectUrl")).concat("/wechat-login/app/notify"));
            queryMap.add("response_type", "code");
            queryMap.add("scope", "snsapi_userinfo");
            queryMap.add("state", UUID.randomUUID().toString());

            request.setAttribute("state", queryMap.get("state"), WebRequest.SCOPE_SESSION);

            String codeStr = UriComponentsBuilder.fromUriString(this.env.getProperty("wechat.authorizeUrl"))
                    .queryParams(queryMap)
                    .build()
                    .toUriString()
                    .concat("#wechat_redirect");

            System.out.println(codeStr);
            response.sendRedirect(codeStr);
            return null;
        }
        return null;
    }

    @GetMapping(value = "/notify", produces = "application/json;charset=UTF-8")
    public String getUser(String code, String state, WebRequest request) {
        Assert.notNull(code, "code不能为空");
        Assert.notNull(state, "state不能为空");

//        boolean stateEq = request.getAttribute("state", WebRequest.SCOPE_SESSION).equals(state);
//        if(!stateEq)
//            throw new RuntimeException("非法操作！");

        MultiValueMap<String, String> queryMap = new LinkedMultiValueMap<>();
        queryMap.add("appid", env.getProperty("wechat.appid"));
        queryMap.add("secret", env.getProperty("wechat.secret"));
        queryMap.add("code", code);
        queryMap.add("grant_type", "authorization_code");

        URI uri = UriComponentsBuilder.fromUriString(this.env.getProperty("wechat.tokenUrl"))
                .queryParams(queryMap)
                .build()
                .toUri();

        var forObj = getRestTemplate().getForObject(uri, Map.class);

        System.out.println(forObj);
        String token = forObj.get("access_token").toString();
        String openid = forObj.get("openid").toString();

        queryMap.clear();

        queryMap.add("access_token", token);
        queryMap.add("openid", openid);
        queryMap.add("lang", "zh_CN");

        return JSONObject.toJSONString(getRestTemplate().getForObject(
                UriComponentsBuilder.fromUriString(this.env.getProperty("wechat.userInfoUrl"))
                        .queryParams(queryMap)
                        .build()
                        .toUri(), Map.class));
    }

    private RestTemplate getRestTemplate() {
        List<HttpMessageConverter<?>> messageConverters = new RestTemplate().getMessageConverters();
        messageConverters.add(new FastJsonHttpMessageConverter());
        return new RestTemplate(messageConverters);
    }

}
